/*
 * Copyright (C) 2013 47 Degrees, LLC
 * http://47deg.com
 * hello@47deg.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.pansoft.androidcomp.swipepulllistview;

import java.util.List;
import android.content.Context;
import android.database.DataSetObserver;
import android.os.Handler;
import androidx.core.view.MotionEventCompat;
import androidx.core.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;

import com.pansoft.espcomp.esplistview.LastRefreshTime;
import com.pansoft.android.espbase.R;

/**
 * ListView subclass that provides the swipe functionality
 */
public class SwipePullListView extends ListView implements OnScrollListener {

	private final static String TAG = "SwipePullListView";
	
	
	// 用于下拉刷新更新界面的handler
	private Handler handler = new Handler();

	

	/* ---------------------- 以下成员来自oschina下拉刷新项目 ----------------------- */

	// 下拉刷新标志
	private final static int PULL_To_REFRESH = 0;
	// 松开刷新标志
	private final static int RELEASE_To_REFRESH = 1;
	// 正在刷新标志
	private final static int REFRESHING = 2;
	// 刷新完成标志
	private final static int DONE = 3;

	private LayoutInflater inflater;

	private LinearLayout headView;
	private TextView tipsTextview;
	private TextView lastUpdatedTextView;
	private ImageView arrowImageView;
	private ProgressBar progressBar;
	// 用来设置箭头图标动画效果
	private RotateAnimation animation;
	private RotateAnimation reverseAnimation;

	// 用于保证startY的值在一个完整的touch事件中只被记录一次
	private boolean isRecored;

	private int headContentWidth;
	private int headContentHeight;
	private int headContentOriginalTopPadding;

	private int startY;
	private int firstItemIndex;
	private int currentScrollState;

	private int state;

	private boolean isBack;

	public OnRefreshListener refreshListener;

	/* ----------------------- 以上成员来自下拉刷新项目 ----------------------*/

	
	
	/**
	 * 解决两个项目中OnScrollListener的冲突 zhangjg
	 */
	private OnScrollListener swipScrollListener;

	
	
	
	/*--------------------以下成员来自swiplistview项目----------------------*/

	/**
	 * Used when user want change swipe list mode on some rows
	 */
	public final static int SWIPE_MODE_DEFAULT = -1;

	/**
	 * Disables all swipes
	 */
	public final static int SWIPE_MODE_NONE = 0;

	/**
	 * Enables both left and right swipe
	 */
	public final static int SWIPE_MODE_BOTH = 1;

	/**
	 * Enables right swipe
	 */
	public final static int SWIPE_MODE_RIGHT = 2;

	/**
	 * Enables left swipe
	 */
	public final static int SWIPE_MODE_LEFT = 3;

	/**
	 * Binds the swipe gesture to reveal a view behind the row (Drawer style)
	 */
	public final static int SWIPE_ACTION_REVEAL = 0;

	/**
	 * Dismisses the cell when swiped over
	 */
	public final static int SWIPE_ACTION_DISMISS = 1;

	/**
	 * Marks the cell as checked when swiped and release
	 */
	public final static int SWIPE_ACTION_CHOICE = 2;

	/**
	 * No action when swiped
	 */
	public final static int SWIPE_ACTION_NONE = 3;

	/**
	 * Default ids for front view
	 */
	public final static String SWIPE_DEFAULT_FRONT_VIEW = "swipelist_frontview";

	/**
	 * Default id for back view
	 */
	public final static String SWIPE_DEFAULT_BACK_VIEW = "swipelist_backview";

	/**
	 * Indicates no movement
	 */
	private final static int TOUCH_STATE_REST = 0;

	/**
	 * State scrolling x position
	 */
	private final static int TOUCH_STATE_SCROLLING_X = 1;

	/**
	 * State scrolling y position
	 */
	private final static int TOUCH_STATE_SCROLLING_Y = 2;

	private int touchState = TOUCH_STATE_REST;

	private float lastMotionX;
	private float lastMotionY;
	private int touchSlop;

	protected int swipeFrontView = 0;
	protected int swipeBackView = 0;

	/**
	 * Internal listener for common swipe events
	 */
	private SwipeListViewListener swipeListViewListener;

	/**
	 * Internal touch listener
	 */
	private SwipeListViewTouchListener touchListener;

	/**
	 * If you create a View programmatically you need send back and front
	 * identifier
	 * 
	 * @param context
	 *            Context
	 * @param swipeBackView
	 *            Back Identifier
	 * @param swipeFrontView
	 *            Front Identifier
	 */
	public SwipePullListView(Context context/*, int swipeBackView, int swipeFrontView*/) {
		super(context);
		
		
		this.swipeFrontView = R.id.swipe_front;
		this.swipeBackView = R.id.swipe_back;
		
		initSwipe(null);

		initPullToRefresh(context);
	}

	/**
	 * @see android.widget.ListView#ListView(android.content.Context,
	 *      android.util.AttributeSet)
	 */
	public SwipePullListView(Context context, AttributeSet attrs) {
		super(context, attrs);

		this.swipeFrontView = R.id.swipe_front;
		this.swipeBackView = R.id.swipe_back;
		
		initSwipe(attrs);

		initPullToRefresh(context);
	}

	/**
	 * @see android.widget.ListView#ListView(android.content.Context,
	 *      android.util.AttributeSet, int)
	 */
	public SwipePullListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		this.swipeFrontView = R.id.swipe_front;
		this.swipeBackView = R.id.swipe_back;
		
		initSwipe(attrs);

		initPullToRefresh(context);
	}

	/**
	 * Init ListView
	 * 
	 * @param attrs
	 *            AttributeSet
	 */
	private void initSwipe(AttributeSet attrs) {

		int swipeMode = SWIPE_MODE_BOTH;
		boolean swipeOpenOnLongPress = true;
		boolean swipeCloseAllItemsWhenMoveList = true;
		long swipeAnimationTime = 0;
		float swipeOffsetLeft = 0;
		float swipeOffsetRight = 0;
		int swipeDrawableChecked = 0;
		int swipeDrawableUnchecked = 0;

		int swipeActionLeft = SWIPE_ACTION_REVEAL;
		int swipeActionRight = SWIPE_ACTION_REVEAL;

		/**
		 * 以下代码用于从xml中读取属性, 在本项目中不会用到, 先注掉
		 * zhangjg 2013 12 16
		 */
//		if (attrs != null) {
//			TypedArray styled = getContext().obtainStyledAttributes(attrs,
//					R.styleable.SwipePullListView);
//			swipeMode = styled.getInt(R.styleable.SwipePullListView_swipeMode,
//					SWIPE_MODE_BOTH);
//
//			swipeActionLeft = styled.getInt(
//					R.styleable.SwipePullListView_swipeActionLeft,
//					SWIPE_ACTION_REVEAL);
//
//			swipeActionRight = styled.getInt(
//					R.styleable.SwipePullListView_swipeActionRight,
//					SWIPE_ACTION_REVEAL);
//
//			swipeOffsetLeft = styled.getDimension(
//					R.styleable.SwipePullListView_swipeOffsetLeft, 0);
//
//			swipeOffsetRight = styled.getDimension(
//					R.styleable.SwipePullListView_swipeOffsetRight, 0);
//
//			swipeOpenOnLongPress = styled.getBoolean(
//					R.styleable.SwipePullListView_swipeOpenOnLongPress, true);
//
//			swipeAnimationTime = styled.getInteger(
//					R.styleable.SwipePullListView_swipeAnimationTime, 0);
//
//			swipeCloseAllItemsWhenMoveList = styled.getBoolean(
//					R.styleable.SwipePullListView_swipeCloseAllItemsWhenMoveList,
//					true);
//
//			swipeDrawableChecked = styled.getResourceId(
//					R.styleable.SwipePullListView_swipeDrawableChecked, 0);
//
//			swipeDrawableUnchecked = styled.getResourceId(
//					R.styleable.SwipePullListView_swipeDrawableUnchecked, 0);
//
//			swipeFrontView = styled.getResourceId(
//					R.styleable.SwipePullListView_swipeFrontView, 0);
//
//			swipeBackView = styled.getResourceId(
//					R.styleable.SwipePullListView_swipeBackView, 0);
//
//		}

		if (swipeFrontView == 0 || swipeBackView == 0) {
			swipeFrontView = getContext().getResources().getIdentifier(
					SWIPE_DEFAULT_FRONT_VIEW, "id",
					getContext().getPackageName());
			swipeBackView = getContext().getResources().getIdentifier(
					SWIPE_DEFAULT_BACK_VIEW, "id",
					getContext().getPackageName());

			if (swipeFrontView == 0 || swipeBackView == 0) {
				throw new RuntimeException(
						String.format(
								"You forgot the attributes swipeFrontView or swipeBackView. You can add this attributes or use '%s' and '%s' identifiers",
								SWIPE_DEFAULT_FRONT_VIEW,
								SWIPE_DEFAULT_BACK_VIEW));
			}
		}

		final ViewConfiguration configuration = ViewConfiguration
				.get(getContext());
		touchSlop = ViewConfigurationCompat
				.getScaledPagingTouchSlop(configuration);
		touchListener = new SwipeListViewTouchListener(this, swipeFrontView,
				swipeBackView);
		if (swipeAnimationTime > 0) {
			touchListener.setAnimationTime(swipeAnimationTime);
		}
		touchListener.setRightOffset(swipeOffsetRight);
		touchListener.setLeftOffset(swipeOffsetLeft);
		touchListener.setSwipeActionLeft(swipeActionLeft);
		touchListener.setSwipeActionRight(swipeActionRight);

		touchListener.setSwipeMode(swipeMode);
		touchListener
				.setSwipeClosesAllItemsWhenListMoves(swipeCloseAllItemsWhenMoveList);
		touchListener.setSwipeOpenOnLongPress(swipeOpenOnLongPress);
		touchListener.setSwipeDrawableChecked(swipeDrawableChecked);
		touchListener.setSwipeDrawableUnchecked(swipeDrawableUnchecked);
		setOnTouchListener(touchListener);
		
		
		/**
		 * 为了解决两个项目中ScrollListener的冲突问题  zhangjg
		 */
		// setOnScrollListener(touchListener.makeScrollListener());
		this.swipScrollListener = touchListener.makeScrollListener();

	}

	/**
	 * Recycle cell. This method should be called from getView in Adapter when
	 * use SWIPE_ACTION_CHOICE
	 * 
	 * @param convertView
	 *            parent view
	 * @param position
	 *            position in list
	 */
	public void recycle(View convertView, int position) {
		touchListener.reloadChoiceStateInView(
				convertView.findViewById(swipeFrontView), position);
	}

	/**
	 * Get if item is selected
	 * 
	 * @param position
	 *            position in list
	 * @return
	 */
	public boolean isChecked(int position) {
		return touchListener.isChecked(position);
	}

	/**
	 * Get positions selected
	 * 
	 * @return
	 */
	public List<Integer> getPositionsSelected() {
		return touchListener.getPositionsSelected();
	}

	/**
	 * Count selected
	 * 
	 * @return
	 */
	public int getCountSelected() {
		return touchListener.getCountSelected();
	}

	/**
	 * Unselected choice state in item
	 */
	public void unselectedChoiceStates() {
		touchListener.unselectedChoiceStates();
	}

	/**
	 * @see android.widget.ListView#setAdapter(android.widget.ListAdapter)
	 */
	@Override
	public void setAdapter(ListAdapter adapter) {
		super.setAdapter(adapter);
		touchListener.resetItems();
		adapter.registerDataSetObserver(new DataSetObserver() {
			@Override
			public void onChanged() {
				super.onChanged();
				onListChanged();
				touchListener.resetItems();
			}
		});
	}

	/**
	 * Dismiss item
	 * 
	 * @param position
	 *            Position that you want open
	 */
	public void dismiss(int position) {
		int height = touchListener.dismiss(position);
		if (height > 0) {
			touchListener.handlerPendingDismisses(height);
		} else {
			int[] dismissPositions = new int[1];
			dismissPositions[0] = position;
			onDismiss(dismissPositions);
			touchListener.resetPendingDismisses();
		}
	}

	/**
	 * Dismiss items selected
	 */
	public void dismissSelected() {
		List<Integer> list = touchListener.getPositionsSelected();
		int[] dismissPositions = new int[list.size()];
		int height = 0;
		for (int i = 0; i < list.size(); i++) {
			int position = list.get(i);
			dismissPositions[i] = position;
			int auxHeight = touchListener.dismiss(position);
			if (auxHeight > 0) {
				height = auxHeight;
			}
		}
		if (height > 0) {
			touchListener.handlerPendingDismisses(height);
		} else {
			onDismiss(dismissPositions);
			touchListener.resetPendingDismisses();
		}
		touchListener.returnOldActions();
	}

	/**
	 * Open ListView's item
	 * 
	 * @param position
	 *            Position that you want open
	 */
	public void openAnimate(int position) {
		touchListener.openAnimate(position);
	}

	/**
	 * Close ListView's item
	 * 
	 * @param position
	 *            Position that you want open
	 */
	public void closeAnimate(int position) {
		touchListener.closeAnimate(position);
	}

	/**
	 * Notifies onDismiss
	 * 6
	 * @param reverseSortedPositions
	 *            All dismissed positions
	 */
	protected void onDismiss(int[] reverseSortedPositions) {
		if (swipeListViewListener != null) {
			swipeListViewListener.onDismiss(reverseSortedPositions);
		}
	}

	/**
	 * Start open item
	 * 
	 * @param position
	 *            list item
	 * @param action
	 *            current action
	 * @param right
	 *            to right
	 */
	protected void onStartOpen(int position, int action, boolean right) {
		if (swipeListViewListener != null
				&& position != ListView.INVALID_POSITION) {
			
			
			swipeListViewListener.onStartOpen(position, action, right);
		}
		
		
		int dataPosition = position - getHeaderViewsCount();
		onStartOpen(position, dataPosition, action,  right);
	}
	
    /**
     * 如果该listview被加入了headview, 这个position和数据的索引不能对应, 这里对position进行修正
     * 以让position和数据的索引相对应
     * 
     * zhangjg 2013 12 17
     */
	protected void onStartOpen(int itemPosition, int dataPosition, int action, boolean right) {
		
	}
	
	
	
	
	/**
	 * Start close item
	 * 
	 * @param position
	 *            list item
	 * @param right
	 */
	protected void onStartClose(int position, boolean right) {
		if (swipeListViewListener != null
				&& position != ListView.INVALID_POSITION) {
			swipeListViewListener.onStartClose(position, right);
		}
		
		int dataPosition = position - getHeaderViewsCount();
		onStartClose(position, dataPosition,   right);
	}
	
	 /**
     * 如果该listview被加入了headview, 这个position和数据的索引不能对应, 这里对position进行修正
     * 以让position和数据的索引相对应
     * 
     * zhangjg 2013 12 17
     */
	protected void onStartClose(int itemPosition, int dataPosition, boolean right) {
		
	}

	/**
	 * Notifies onClickFrontView
	 * 
	 * @param position
	 *            item clicked
	 */
	protected void onClickFrontView(int position) {
		if (swipeListViewListener != null
				&& position != ListView.INVALID_POSITION) {
			swipeListViewListener.onClickFrontView(position);
		}
		
		int dataPosition = position - getHeaderViewsCount();
		onClickFrontView(position, dataPosition);
	}
	
	 /**
     * 如果该listview被加入了headview, 这个position和数据的索引不能对应, 这里对position进行修正
     * 以让position和数据的索引相对应
     * 
     * zhangjg 2013 12 17
     */
	protected void onClickFrontView(int itemPosition, int dataPosition) {
		
		/**
		 * 为了测试  zhangjg
		 */
		if(this.getOnItemClickListener() != null){
			this.getOnItemClickListener().onItemClick(this, null, itemPosition, 0);
		}
	}

	/**
	 * Notifies onClickBackView
	 * 
	 * @param position
	 *            back item clicked
	 */
	protected void onClickBackView(int position) {
		if (swipeListViewListener != null
				&& position != ListView.INVALID_POSITION) {
			swipeListViewListener.onClickBackView(position);
		}
		
		int dataPosition = position - getHeaderViewsCount();
		onClickBackView(position, dataPosition);

	}
	
	 /**
     * 如果该listview被加入了headview, 这个position和数据的索引不能对应, 这里对position进行修正
     * 以让position和数据的索引相对应
     * 
     * zhangjg 2013 12 17
     */
	protected void onClickBackView(int itemPosition, int dataPosition) {
		
	}

	/**
	 * Notifies onOpened
	 * 
	 * @param position
	 *            Item opened
	 * @param toRight
	 *            If should be opened toward the right
	 */
	protected void onOpened(int position, boolean toRight) {
		if (swipeListViewListener != null
				&& position != ListView.INVALID_POSITION) {
			swipeListViewListener.onOpened(position, toRight);
		}
		
		int dataPosition = position - getHeaderViewsCount();
		onOpened(position, dataPosition, toRight);
		
	}

	 /**
     * 如果该listview被加入了headview, 这个position和数据的索引不能对应, 这里对position进行修正
     * 以让position和数据的索引相对应
     * 
     * zhangjg 2013 12 17
     */
	protected void onOpened(int itemPosition, int dataPosition, boolean toRight) {
		
	}
	
	
	/**
	 * Notifies onClosed
	 * 
	 * @param position
	 *            Item closed
	 * @param fromRight
	 *            If open from right
	 */
	protected void onClosed(int position, boolean fromRight) {
		if (swipeListViewListener != null
				&& position != ListView.INVALID_POSITION) {
			swipeListViewListener.onClosed(position, fromRight);
		}
		
		int dataPosition = position - getHeaderViewsCount();
		onClosed(position, dataPosition, fromRight);
	}
	
	 /**
     * 如果该listview被加入了headview, 这个position和数据的索引不能对应, 这里对position进行修正
     * 以让position和数据的索引相对应
     * 
     * zhangjg 2013 12 17
     */
	protected void onClosed(int itemPosition, int dataPosition, boolean fromRight) {
		
	}

	/**
	 * Notifies onChoiceChanged
	 * 
	 * @param position
	 *            position that choice
	 * @param selected
	 *            if item is selected or not
	 */
	protected void onChoiceChanged(int position, boolean selected) {
		if (swipeListViewListener != null
				&& position != ListView.INVALID_POSITION) {
			swipeListViewListener.onChoiceChanged(position, selected);
		}
		
		int dataPosition = position - getHeaderViewsCount();
		onChoiceChanged(position, dataPosition, selected);
	}
	
	 /**
     * 如果该listview被加入了headview, 这个position和数据的索引不能对应, 这里对position进行修正
     * 以让position和数据的索引相对应
     * 
     * zhangjg 2013 12 17
     */
	protected void onChoiceChanged(int itemPosition, int dataPosition, boolean selected) {
		
	}
	

	/**
	 * User start choice items
	 */
	protected void onChoiceStarted() {
		if (swipeListViewListener != null) {
			swipeListViewListener.onChoiceStarted();
		}
	}

	/**
	 * User end choice items
	 */
	protected void onChoiceEnded() {
		if (swipeListViewListener != null) {
			swipeListViewListener.onChoiceEnded();
		}
	}

	/**
	 * User is in first item of list
	 */
	protected void onFirstListItem() {
		if (swipeListViewListener != null) {
			swipeListViewListener.onFirstListItem();
		}
	}

	/**
	 * User is in last item of list
	 */
	protected void onLastListItem() {
		if (swipeListViewListener != null) {
			swipeListViewListener.onLastListItem();
		}
	}

	/**
	 * Notifies onListChanged
	 */
	protected void onListChanged() {
		if (swipeListViewListener != null) {
			swipeListViewListener.onListChanged();
		}
	}

	/**
	 * Notifies onMove
	 * 
	 * @param position
	 *            Item moving
	 * @param x
	 *            Current position
	 */
	protected void onMove(int position, float x) {
		if (swipeListViewListener != null
				&& position != ListView.INVALID_POSITION) {
			swipeListViewListener.onMove(position, x);
		}
		
		int dataPosition = position - getHeaderViewsCount();
		onMove(position, dataPosition, x);
	}
	
	 /**
     * 如果该listview被加入了headview, 这个position和数据的索引不能对应, 这里对position进行修正
     * 以让position和数据的索引相对应
     * 
     * zhangjg 2013 12 17
     */
	protected void onMove(int itemPosition, int dataPosition, float x) {
		
	}

	protected int changeSwipeMode(int position) {
		if (swipeListViewListener != null
				&& position != ListView.INVALID_POSITION) {
			return swipeListViewListener.onChangeSwipeMode(position);
		}
		return SWIPE_MODE_DEFAULT;
	}

	/**
	 * Sets the Listener
	 * 
	 * @param swipeListViewListener
	 *            Listener
	 */
	public void setSwipeListViewListener(
			SwipeListViewListener swipeListViewListener) {
		this.swipeListViewListener = swipeListViewListener;
	}

	/**
	 * Resets scrolling
	 */
	public void resetScrolling() {
		touchState = TOUCH_STATE_REST;
	}

	/**
	 * Set offset on right
	 * 
	 * @param offsetRight
	 *            Offset
	 */
	public void setOffsetRight(float offsetRight) {
		touchListener.setRightOffset(offsetRight);
	}

	/**
	 * Set offset on left
	 * 
	 * @param offsetLeft
	 *            Offset
	 */
	public void setOffsetLeft(float offsetLeft) {
		touchListener.setLeftOffset(offsetLeft);
	}

	/**
	 * Set if all items opened will be closed when the user moves the ListView
	 * 
	 * @param swipeCloseAllItemsWhenMoveList
	 */
	public void setSwipeCloseAllItemsWhenMoveList(
			boolean swipeCloseAllItemsWhenMoveList) {
		touchListener
				.setSwipeClosesAllItemsWhenListMoves(swipeCloseAllItemsWhenMoveList);
	}

	/**
	 * Sets if the user can open an item with long pressing on cell
	 * 
	 * @param swipeOpenOnLongPress
	 */
	public void setSwipeOpenOnLongPress(boolean swipeOpenOnLongPress) {
		touchListener.setSwipeOpenOnLongPress(swipeOpenOnLongPress);
	}

	/**
	 * Set swipe mode
	 * 
	 * @param swipeMode
	 */
	public void setSwipeMode(int swipeMode) {
		touchListener.setSwipeMode(swipeMode);
	}

	/**
	 * Return action on left
	 * 
	 * @return Action
	 */
	public int getSwipeActionLeft() {
		return touchListener.getSwipeActionLeft();
	}

	/**
	 * Set action on left
	 * 
	 * @param swipeActionLeft
	 *            Action
	 */
	public void setSwipeActionLeft(int swipeActionLeft) {
		touchListener.setSwipeActionLeft(swipeActionLeft);
	}

	/**
	 * Return action on right
	 * 
	 * @return Action
	 */
	public int getSwipeActionRight() {
		return touchListener.getSwipeActionRight();
	}

	/**
	 * Set action on right
	 * 
	 * @param swipeActionRight
	 *            Action
	 */
	public void setSwipeActionRight(int swipeActionRight) {
		touchListener.setSwipeActionRight(swipeActionRight);
	}

	/**
	 * Sets animation time when user drops cell
	 * 
	 * @param animationTime
	 *            milliseconds
	 */
	public void setAnimationTime(long animationTime) {
		touchListener.setAnimationTime(animationTime);
	}

	/**
	 * @see android.widget.ListView#onInterceptTouchEvent(android.view.MotionEvent)
	 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		int action = MotionEventCompat.getActionMasked(ev);
		final float x = ev.getX();
		final float y = ev.getY();

		if (isEnabled() && touchListener.isSwipeEnabled()) {

			if (touchState == TOUCH_STATE_SCROLLING_X) {
				return touchListener.onTouch(this, ev);
			}

			switch (action) {
			case MotionEvent.ACTION_MOVE:
				checkInMoving(x, y);
				return touchState == TOUCH_STATE_SCROLLING_Y;
			case MotionEvent.ACTION_DOWN:
				touchListener.onTouch(this, ev);
				touchState = TOUCH_STATE_REST;
				lastMotionX = x;
				lastMotionY = y;
				return false;
			case MotionEvent.ACTION_CANCEL:
				touchState = TOUCH_STATE_REST;
				break;
			case MotionEvent.ACTION_UP:
				touchListener.onTouch(this, ev);
				return touchState == TOUCH_STATE_SCROLLING_Y;
			default:
				break;
			}
		}

		return super.onInterceptTouchEvent(ev);
	}

	/**
	 * Check if the user is moving the cell
	 * 
	 * @param x
	 *            Position X
	 * @param y
	 *            Position Y
	 */
	private void checkInMoving(float x, float y) {
		final int xDiff = (int) Math.abs(x - lastMotionX);
		final int yDiff = (int) Math.abs(y - lastMotionY);

		final int touchSlop = this.touchSlop;
		boolean xMoved = xDiff > touchSlop;
		boolean yMoved = yDiff > touchSlop;

		if (xMoved) {
			touchState = TOUCH_STATE_SCROLLING_X;
			lastMotionX = x;
			lastMotionY = y;
		}

		if (yMoved) {
			touchState = TOUCH_STATE_SCROLLING_Y;
			lastMotionX = x;
			lastMotionY = y;
		}
	}

	/**
	 * Close all opened items
	 */
	public void closeOpenedItems() {
		touchListener.closeOpenedItems();
	}

	/* -------------------------- 以下代码来自oschina下拉刷新组件 -------------------------- */
	
	
	private void initPullToRefresh(Context context) {
		// 设置滑动效果
		animation = new RotateAnimation(0, -180,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		animation.setInterpolator(new LinearInterpolator());
		animation.setDuration(100);
		animation.setFillAfter(true);

		reverseAnimation = new RotateAnimation(-180, 0,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		reverseAnimation.setInterpolator(new LinearInterpolator());
		reverseAnimation.setDuration(100);
		reverseAnimation.setFillAfter(true);

		inflater = LayoutInflater.from(context);
		headView = (LinearLayout) inflater.inflate(
				R.layout.pull_to_refresh_head, null);

		arrowImageView = (ImageView) headView
				.findViewById(R.id.head_arrowImageView);
		arrowImageView.setMinimumWidth(50);
		arrowImageView.setMinimumHeight(50);
		progressBar = (ProgressBar) headView
				.findViewById(R.id.head_progressBar);
		tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);
		lastUpdatedTextView = (TextView) headView
				.findViewById(R.id.head_lastUpdatedTextView);

		headContentOriginalTopPadding = headView.getPaddingTop();

		measureView(headView);
		headContentHeight = headView.getMeasuredHeight();
		headContentWidth = headView.getMeasuredWidth();

		headView.setPadding(headView.getPaddingLeft(), -1 * headContentHeight,
				headView.getPaddingRight(), headView.getPaddingBottom());
		headView.invalidate();

		// System.out.println("初始高度："+headContentHeight);
		// System.out.println("初始TopPad："+headContentOriginalTopPadding);

		addHeaderView(headView);
		setOnScrollListener(this);
	}

	/**
	 * 该方法来自oschina下拉刷新, 但加入了调用swipScrollListener同名方法的逻辑
	 */
	public void onScroll(AbsListView view, int firstVisiableItem,
			int visibleItemCount, int totalItemCount) {
		firstItemIndex = firstVisiableItem;

		// 为了解决两个项目中ScrollListener的冲突问题
		swipScrollListener.onScroll(view, firstVisiableItem, visibleItemCount,
				totalItemCount);

	}

	/**
	 * 该方法来自oschina下拉刷新, 但加入了调用swipScrollListener同名方法的逻辑
	 */
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		currentScrollState = scrollState;

		// 为了解决两个项目中ScrollListener的冲突问题
		swipScrollListener.onScrollStateChanged(view, scrollState);
	}

	/**
	 * 处理下拉刷新的触摸事件
	 */
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (firstItemIndex == 0 && !isRecored) {
				startY = (int) event.getY();
				isRecored = true;
				// System.out.println("当前-按下高度-ACTION_DOWN-Y："+startY);
			}
			break;

		case MotionEvent.ACTION_CANCEL:// 失去焦点&取消动作
		case MotionEvent.ACTION_UP:

			if (state != REFRESHING) {
				if (state == DONE) {
					// System.out.println("当前-抬起-ACTION_UP：DONE什么都不做");
				} else if (state == PULL_To_REFRESH) {
					state = DONE;
					changeHeaderViewByState();
					// System.out.println("当前-抬起-ACTION_UP：PULL_To_REFRESH-->DONE-由下拉刷新状态到刷新完成状态");
				} else if (state == RELEASE_To_REFRESH) {
					state = REFRESHING;
					changeHeaderViewByState();
					onRefresh();
					// System.out.println("当前-抬起-ACTION_UP：RELEASE_To_REFRESH-->REFRESHING-由松开刷新状态，到刷新完成状态");
				}
			}

			isRecored = false;
			isBack = false;

			break;

		case MotionEvent.ACTION_MOVE:
			int tempY = (int) event.getY();
			// System.out.println("当前-滑动-ACTION_MOVE Y："+tempY);
			if (!isRecored && firstItemIndex == 0) {
				// System.out.println("当前-滑动-记录拖拽时的位置 Y："+tempY);
				isRecored = true;
				startY = tempY;
			}
			if (state != REFRESHING && isRecored) {
				// 可以松开刷新了
				if (state == RELEASE_To_REFRESH) {
					// 往上推，推到屏幕足够掩盖head的程度，但还没有全部掩盖
					if ((tempY - startY < headContentHeight + 20)
							&& (tempY - startY) > 0) {
						state = PULL_To_REFRESH;
						changeHeaderViewByState();
						// System.out.println("当前-滑动-ACTION_MOVE：RELEASE_To_REFRESH--》PULL_To_REFRESH-由松开刷新状态转变到下拉刷新状态");
					}
					// 一下子推到顶
					else if (tempY - startY <= 0) {
						state = DONE;
						changeHeaderViewByState();
						// System.out.println("当前-滑动-ACTION_MOVE：RELEASE_To_REFRESH--》DONE-由松开刷新状态转变到done状态");
					}
					// 往下拉，或者还没有上推到屏幕顶部掩盖head
					else {
						// 不用进行特别的操作，只用更新paddingTop的值就行了
					}
				}
				// 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
				else if (state == PULL_To_REFRESH) {
					// 下拉到可以进入RELEASE_TO_REFRESH的状态
					if (tempY - startY >= headContentHeight + 20
							&& currentScrollState == SCROLL_STATE_TOUCH_SCROLL) {
						state = RELEASE_To_REFRESH;
						isBack = true;
						changeHeaderViewByState();
						// System.out.println("当前-滑动-PULL_To_REFRESH--》RELEASE_To_REFRESH-由done或者下拉刷新状态转变到松开刷新");
					}
					// 上推到顶了
					else if (tempY - startY <= 0) {
						state = DONE;
						changeHeaderViewByState();
						// System.out.println("当前-滑动-PULL_To_REFRESH--》DONE-由Done或者下拉刷新状态转变到done状态");
					}
				}
				// done状态下
				else if (state == DONE) {
					if (tempY - startY > 0) {
						state = PULL_To_REFRESH;
						changeHeaderViewByState();
						// System.out.println("当前-滑动-DONE--》PULL_To_REFRESH-由done状态转变到下拉刷新状态");
					}
				}

				// 更新headView的size
				if (state == PULL_To_REFRESH) {
					int topPadding = (int) ((-1 * headContentHeight + (tempY - startY)));
					headView.setPadding(headView.getPaddingLeft(), topPadding,
							headView.getPaddingRight(),
							headView.getPaddingBottom());
					headView.invalidate();
					// System.out.println("当前-下拉刷新PULL_To_REFRESH-TopPad："+topPadding);
				}

				// 更新headView的paddingTop
				if (state == RELEASE_To_REFRESH) {
					int topPadding = (int) ((tempY - startY - headContentHeight));
					headView.setPadding(headView.getPaddingLeft(), topPadding,
							headView.getPaddingRight(),
							headView.getPaddingBottom());
					headView.invalidate();
					// System.out.println("当前-释放刷新RELEASE_To_REFRESH-TopPad："+topPadding);
				}
			}
			break;
		}
		return super.onTouchEvent(event);
	}

	/*
	 * 当状态改变时候，调用该方法，以更新界面
	 */
	private void changeHeaderViewByState() {
		switch (state) {
		case RELEASE_To_REFRESH:

			arrowImageView.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.GONE);
			tipsTextview.setVisibility(View.VISIBLE);
			lastUpdatedTextView.setVisibility(View.VISIBLE);

			arrowImageView.clearAnimation();
			arrowImageView.startAnimation(animation);

			tipsTextview.setText("松开刷新");
			
			String lastRefreshMsg = LastRefreshTime.getLastRefresh(this.getContext());
			lastUpdatedTextView.setText(lastRefreshMsg);

			// Log.v(TAG, "当前状态，松开刷新");
			break;
		case PULL_To_REFRESH:

			progressBar.setVisibility(View.GONE);
			tipsTextview.setVisibility(View.VISIBLE);
			lastUpdatedTextView.setVisibility(View.VISIBLE);
			arrowImageView.clearAnimation();
			arrowImageView.setVisibility(View.VISIBLE);
			if (isBack) {
				isBack = false;
				arrowImageView.clearAnimation();
				arrowImageView.startAnimation(reverseAnimation);
			}
			tipsTextview.setText("下拉刷新");
			
			//zhangjg 2013 12 17

			// Log.v(TAG, "当前状态，下拉刷新");
			break;

		case REFRESHING:
			// System.out.println("刷新REFRESHING-TopPad："+headContentOriginalTopPadding);
			headView.setPadding(headView.getPaddingLeft(),
					headContentOriginalTopPadding, headView.getPaddingRight(),
					headView.getPaddingBottom());
			headView.invalidate();

			progressBar.setVisibility(View.VISIBLE);
			arrowImageView.clearAnimation();
			arrowImageView.setVisibility(View.GONE);
			tipsTextview.setText("正在刷新");
			
			lastUpdatedTextView.setText("");
			lastUpdatedTextView.setVisibility(View.GONE);
			

			// Log.v(TAG, "当前状态,正在刷新...");
			break;
		case DONE:
			// System.out.println("完成DONE-TopPad："+(-1 * headContentHeight));
			headView.setPadding(headView.getPaddingLeft(), -1
					* headContentHeight, headView.getPaddingRight(),
					headView.getPaddingBottom());
			headView.invalidate();

			progressBar.setVisibility(View.GONE);
			arrowImageView.clearAnimation();
			// 此处更换图标
			arrowImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow);

			tipsTextview.setText("下拉刷新");
			lastUpdatedTextView.setVisibility(View.VISIBLE);

			// Log.v(TAG, "当前状态，done");
			break;
		}
	}

	// 点击刷新
	public void clickRefresh() {
		setSelection(0);
		state = REFRESHING;
		changeHeaderViewByState();
		onRefresh();
	}

	public void setOnRefreshListener(OnRefreshListener refreshListener) {
		this.refreshListener = refreshListener;
	}

	public interface OnRefreshListener {
		public void onRefresh();
	}

	/**
	 * 在子线程被调用
	 */
	private void onRefreshCompleteInner() {
		
		handler.post(new Runnable() {

			/**
			 * 在主线程被调用
			 */
			@Override
			public void run() {
				
				//保存刷新时间
				LastRefreshTime.setLastRefresh(SwipePullListView.this.getContext());
				
				//更新ListView的界面, 隐藏下拉刷新的header
				state = DONE;
				changeHeaderViewByState();
				
				//回调接口, 用于子类覆盖
				onRefreshComplete();
			}
		});
		
		
	}

	/**
	 * 可被子类覆盖,处理特定的逻辑
	 * 该方法在后台刷新完成时被调用, 在主线程中被调用
	 */
	protected void onRefreshComplete() {}

	private void onRefresh() {

		Log.i(TAG, "onRefresh");
		if (refreshListener != null) {
			refreshListener.onRefresh();
		}

		new Thread(new Runnable() {

			@Override
			public void run() {

				//回调接口, 用于子类覆盖
				doRefreshInBackground();
				
				onRefreshCompleteInner();
			}

		}).start();

	}
	
	/**
	 * 在子线程中被调用,处理后台更新
	 * 子类可以直接覆盖该方法
	 * zhangjg 2013 12 17
	 */
	protected void doRefreshInBackground(){}

	/*
	 * 计算headView的width及height值
	 */
	private void measureView(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
		}
		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
					MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0,
					MeasureSpec.UNSPECIFIED);
		}
		child.measure(childWidthSpec, childHeightSpec);
	}
	


}
